package com.crunch.physics;

import com.crunch.math.Linef;
import com.crunch.math.Vector2f;

/**
 * An immutable polygon.
 */
public class Polygon {
	// constructs the polygon, assuming vertices is specified in CCW order
	public Polygon(Vector2f[] vertices) {
		if (vertices == null || vertices.length < 3) {
			throw new IllegalArgumentException("Invalid vertices");
		}

		this.vertices = new Vector2f[vertices.length];
		for (int i = 0; i < vertices.length; ++i) {
			this.vertices[i] = new Vector2f(vertices[i]);
		}
		this.normals = new Vector2f[vertices.length];
		for (int i = 0; i < vertices.length; ++i) {
			int i1 = (i+1 == vertices.length) ? 0 : i+1;
			this.normals[i] = vertices[i1].subtract(vertices[i]);
			this.normals[i].rotateCwAssign();
			this.normals[i].normalizeAssign();
		}

		// check for convexity
		convex = true;
		for (int i = 0; i < vertices.length; ++i) {
			int i1 = (i+1) % vertices.length;
			int i2 = (i+2) % vertices.length;

			Linef line = Linef.line2Points(vertices[i], vertices[i1]);
			float side = line.side(vertices[i2]);

			if (side < 0.0f) {
				convex = false;
			}
		}
	}

	public int getVertexCount() {
		return vertices.length;
	}

	// returns ith vertex
	public Vector2f getVertex(int i) {
		return new Vector2f(vertices[i]);
	}

	// returns normal formed by vertices i and i+1
	public Vector2f getNormal(int i) {
		return new Vector2f(normals[i]);
	}

	// returns ith vertex without copying - for internal use only!
	Vector2f getVertexDirect(int i) {
		return vertices[i];
	}

	// returns ith normal without copying - for internal use only!
	Vector2f getNormalDirect(int i) {
		return normals[i];
	}

	public boolean isConvex() {
		return convex;
	}

	private Vector2f[] vertices;
	private Vector2f[] normals;
	private boolean convex;
}
